package org.mozhu.mboot.admin.maintain.email.service;

import com.google.common.base.Splitter;
import com.google.common.base.Throwables;
import org.apache.commons.lang3.StringUtils;
import org.mozhu.mboot.admin.GlobalSettings;
import org.mozhu.mboot.admin.maintain.email.entity.EmailNotification;
import org.mozhu.mboot.admin.maintain.email.exception.MailSendFailException;
import org.mozhu.mboot.admin.maintain.email.repository.EmailNotificationRepository;
import org.mozhu.mboot.admin.maintain.notification.entity.NotificationModule;
import org.mozhu.mboot.admin.maintain.notification.entity.NotificationTemplate;
import org.mozhu.mboot.admin.maintain.notification.service.NotificationTemplateService;
import org.mozhu.mboot.core.data.BaseService;
import org.mozhu.mboot.core.data.entity.Stateable;
import org.mozhu.mboot.core.template.TemplateRender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 邮件通知 - 业务层实现类
 * 
 * @author ZhangPei
 */
@Transactional
@Service
public class EmailNotificationServiceImpl extends BaseService<EmailNotification, Long> implements EmailNotificationService, EmailService {

	@Autowired
	JavaMailSender mailSender;

	@Autowired
	TemplateRender templateRender;

	@Autowired
	GlobalSettings globalSettings;

	@Autowired
	NotificationTemplateService notificationTemplateService;

	public EmailNotificationRepository getBaseRepository() {
		return (EmailNotificationRepository) baseRepository;
	}

	@Override
	public List<EmailNotification> findPendingEmailNotifications() {
		return getBaseRepository().findByStatus(Stateable.ProcessStatus.pending);
	}

	@Override
	public void sendEmailNotification(EmailNotification emailNotification) {
		try {
			doSend(emailNotification);
			sendSuccess(emailNotification);
		} catch (Exception e) {
			sendFail(emailNotification, e);
		}
	}

	protected void doSend(EmailNotification emailNotification) {
		try {
			logger.debug("Send Email Notification of email[" + emailNotification.getEmail() + "] start");

			SimpleMailMessage message = new SimpleMailMessage();
			message.setFrom(globalSettings.getMailFrom());
			String email = emailNotification.getEmail();
			message.setTo(splitToArrays(email));
			message.setSubject(emailNotification.getTitle());
			message.setText(emailNotification.getContent());
			String mailBcc = globalSettings.getMailBcc();
			if (StringUtils.isBlank(mailBcc)) {
				message.setBcc(splitToArrays(mailBcc));
			}
			mailSender.send(message);

			logger.debug("Send Email Notification of email[" + emailNotification.getEmail() + "] successfully");
		} catch (Exception e) {
			logger.error("Send Email Notification of email[" + emailNotification.getEmail() + "] failed", e);
			throw new MailSendFailException("Send mail failed", e);
		}
	}

	private String[] splitToArrays(String string) {
		return Splitter.on(";").trimResults().omitEmptyStrings().splitToList(string).toArray(new String[0]);
	}

	protected void sendSuccess(EmailNotification emailNotification) {
		emailNotification.setProcessTime(new Date());
		emailNotification.setStatus(Stateable.ProcessStatus.success);
		this.save(emailNotification);
	}

	protected void sendFail(EmailNotification emailNotification, Exception e) {
		emailNotification.setProcessTime(new Date());
		emailNotification.setStatus(Stateable.ProcessStatus.fail);
		emailNotification.setProcessMessage(Throwables.getStackTraceAsString(e));
		this.save(emailNotification);
	}

	@Override
	public void sendByTemplate(String templateCode, String email, Map<String, Object> modal, boolean async) {
		fillCommonData(modal);
		NotificationTemplate notificationTemplate = notificationTemplateService.findByCode(templateCode);
		String title = notificationTemplate.getTitle();
		String content = notificationTemplate.getContent();
		NotificationModule notificationModule = notificationTemplate.getModule();
		EmailNotification emailNotification = new EmailNotification();
		emailNotification.setModule(notificationModule);
		emailNotification.setEmail(email);
		emailNotification.setTitle(title);
		content = templateRender.render(content, modal);
		emailNotification.setContent(content);
		if (async) {
			this.save(emailNotification);
		} else {
			this.doSend(emailNotification);
		}
	}

	private void fillCommonData(Map<String, Object> modal) {
		modal.put("externalUrl", globalSettings.getExternalUrl());
		modal.put("emailSignature", globalSettings.getEmailSignature());
		modal.put("emailSignatureEnglish", globalSettings.getEmailSignatureEnglish());
	}

	@Override
	public void sendByTemplate(String templateCode, String email, Map<String, Object> modal) {
		this.sendByTemplate(templateCode, email, modal, false);
	}

	@Override
	public void asyncSendByTemplate(String templateCode, String email, Map<String, Object> modal) {
		this.sendByTemplate(templateCode, email, modal, true);
	}

}
